﻿using LightCAD.Core;
using LightCAD.Runtime;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using static System.Reflection.Metadata.BlobBuilder;

namespace LightCAD.UI
{
    public partial class PropertyControl : DockContent, IPropertyControl
    {
        private Dictionary<ElementType, List<LcElement>> grpEles;
        private List<PropertyObserver> eleObservers;
        private Dictionary<ElementType, List<PropertyObserver>> eleTypeObservers;
        private List<PropertyObserver> mergeAll;
        private Action<List<LcElement>> propertyChangedAction;

        private List<LcElement> curEles;
        public PropertyControl()
        {
            InitializeComponent();
        }

        public void SelectsChanged(Dictionary<ElementType, List<LcElement>> grpEles, List<PropertyObserver> eleObservers, Dictionary<ElementType, List<PropertyObserver>> eleTypeObservers, List<PropertyObserver> mergeAll, Action<List<LcElement>> propertyChangedAction)
        {
            this.dgvProps.Rows.Clear();
            this.cboEleTypes.Items.Clear();
            this.cboEleTypes.Text = "无选择";
            if (grpEles.Count == 0)
            {
                return;
            }

            this.grpEles = grpEles;
            this.eleObservers = eleObservers;
            this.eleTypeObservers = eleTypeObservers;
            this.mergeAll = mergeAll;
            this.propertyChangedAction = propertyChangedAction;

            BindTypeName();
        }
        public void PropertyChanged(Dictionary<ElementType, List<LcElement>> grpEles, List<PropertyObserver> eleObservers, Dictionary<ElementType, List<PropertyObserver>> eleTypeObservers, List<PropertyObserver> mergeAll, Action<List<LcElement>> propertyChangedAction)
        {
            this.dgvProps.Rows.Clear();
            this.cboEleTypes.Items.Clear();
            this.cboEleTypes.Text = "无选择";
            if (grpEles.Count == 0)
            {
                return;
            }

            this.grpEles = grpEles;
            this.eleObservers = eleObservers;
            this.eleTypeObservers = eleTypeObservers;
            this.mergeAll = mergeAll;
            this.propertyChangedAction = propertyChangedAction;

            BindTypeName();
        }
        private void BindTypeName()
        {
            if (grpEles.Keys.Count > 1)
            {
                int allTypeCount = this.grpEles.Sum(t => t.Value.Count);
                this.cboEleTypes.Items.Add($"全部({allTypeCount})");
            }
            foreach (var kvp in grpEles)
            {
                string typeName = $"{kvp.Key.ToDisplayName()}({kvp.Value.Count})";
                this.cboEleTypes.Items.Add(typeName);
            }

            this.cboEleTypes.SelectedIndex = 0;
        }

        private void cboEleTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.dgvProps.CellValueChanged -= dgvProps_CellValueChanged;
            this.dgvProps.Rows.Clear();
            string selEleType = this.cboEleTypes.Text;

            if (selEleType.StartsWith("全部"))
            {
                var observers = eleObservers.Concat(mergeAll).ToList();
                this.curEles = this.grpEles.SelectMany(P => P.Value).ToList();
                BindProperties(this.curEles, observers);
                return;
            }

            this.curEles = this.grpEles.FirstOrDefault(G => selEleType.StartsWith(G.Key.ToDisplayName())).Value;
            var selObs = this.eleTypeObservers.FirstOrDefault(G => selEleType.StartsWith(G.Key.ToDisplayName())).Value;
            selObs = eleObservers.Concat(selObs).ToList();
            BindProperties(this.curEles, selObs);

            this.dgvProps.CellValueChanged += dgvProps_CellValueChanged;
        }

        private void BindProperties(List<LcElement> eles, List<PropertyObserver> obs)
        {
            var elePropDic = new Dictionary<string, object>();
            foreach (PropertyObserver ob in obs)
            {
                foreach (LcElement ele in eles)
                {
                    var propValue = ob.Getter(ele);

                    if (!elePropDic.ContainsKey(ob.DisplayName))
                    {
                        elePropDic.Add(ob.DisplayName, propValue);
                        continue;
                    }

                    if (!elePropDic[ob.DisplayName].Equals(propValue))
                    {
                        elePropDic[ob.DisplayName] = "*多种*";
                        break;
                    }
                }
            }

            int i = 0;
            foreach (var kvp in elePropDic)
            {
                var curOb = obs[i];
                var drIdx = this.dgvProps.Rows.Add();
                var dr = this.dgvProps.Rows[drIdx];
                dr.Tag = curOb;
                dr.Cells["colTitle"].Value = kvp.Key;
                dr.Cells["colValue"].Value = kvp.Value;
                if (curOb.Setter == null)
                {
                    dr.Cells["colValue"].ReadOnly = true;
                }
                i++;
                //dr.ReadOnly = true;
            }
        }

        private void dgvProps_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            var dr = this.dgvProps.Rows[e.RowIndex];
            var ob = dr.Tag as PropertyObserver;
            var newValue = dr.Cells[e.ColumnIndex].Value;

            foreach (var ele in this.curEles)
            {
                ob.Setter(ele, newValue);
            }

            this.propertyChangedAction?.Invoke(curEles);
        }
    }
}